package com.tanhua.server.service;

import com.tanhua.dubbo.api.*;
import com.tanhua.model.domain.*;
import com.tanhua.model.vo.*;
import com.tanhua.server.interceptor.UserHolder;
import org.apache.dubbo.config.annotation.DubboReference;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.redis.core.RedisTemplate;
import org.springframework.stereotype.Service;

import java.util.ArrayList;
import java.util.List;
import java.util.Map;
import java.util.stream.Collectors;

/**
 * @author pc
 * @date 2021/11/27
 */
@Service
public class TestSoulService {
    @DubboReference
    private QuestionnaireApi questionnaireApi;
    @DubboReference
    private QuestionsApi questionsApi;
    @DubboReference
    private OptionsApi optionsApi;
    @DubboReference
    private ReportApi reportApi;
    @DubboReference
    private UserInfoApi userInfoApi;
    @Autowired
    private RedisTemplate<String, String> redisTemplate;
    // 问卷key
    private final String KEY = "Questionnaires_";
    // 用户hashKey
    private final String HASHKEY = "USER_";

    /**
     * 查询问卷列表
     *
     * @return
     */
    public List<QuestionnaireVo> getQuestionnaires() {
/*        // 查询问卷列表
        List<Questionnaire> questionnaires = questionnaireApi.getQuestionnaires();
        // 获取问卷id
        List<Long> queIds = CollUtil.getFieldValues(questionnaires, "id", Long.class);
        // 获取试题
        List<Questions> subjects = questionsApi.getQuestions(queIds);
        List<Long> subIds = CollUtil.getFieldValues(subjects, "id", Long.class);
        List<Options> options = optionsApi.getOptions(subIds);
        List<QuestionnaireVo> questionnaireVos = new ArrayList<>();
        Integer id = 0;
        for (Questionnaire questionnaire : questionnaires) {
            // 问卷
            List<QuestionsVo> questionsList = new ArrayList<>();
            for (Questions subject : subjects) {
                List<OptionsVo> optionsList = new ArrayList<>();
                if (questionnaire.getId().equals(subject.getQuestionnaireId())) {
                    // 问卷题目
                    for (Options option : options) {
                        // 选项
                        if (subject.getId().equals(option.getSubjectId())) {
                            OptionsVo optionsVo = OptionsVo.init(option);
                            optionsList.add(optionsVo);
                        }
                    }
                    QuestionsVo questionsVo = QuestionsVo.init(subject, optionsList);
                    questionsList.add(questionsVo);
                }
            }
            Integer reportId = reportApi.find(questionnaire.getId(), UserHolder.getId());
            QuestionnaireVo questionnaireVo = QuestionnaireVo.init(questionnaire, questionsList);
            if (reportId != null) {
                questionnaireVo.setReportId(reportId.toString());
            }
            Boolean aBoolean = redisTemplate.opsForHash().hasKey(KEY + id, HASHKEY + UserHolder.getId());
            if (aBoolean) {
                questionnaireVo.setIsLock(0);
            }
            id = questionnaire.getId();
            questionnaireVos.add(questionnaireVo);
        }*/
        // 查询问卷列表
        List<Questionnaire> questionnaires = questionnaireApi.getQuestionnaires();
        List<QuestionnaireVo> questionnaireVos = new ArrayList<>();
        Integer id = 0;
        for (Questionnaire questionnaire : questionnaires) {
            // 获取试题
            List<Questions> questions = questionsApi.getQuestion(questionnaire.getId());
            List<QuestionsVo> questionsVos = new ArrayList<>();
            for (Questions question : questions) {
                // 获取选项
                List<Options> options = optionsApi.getOption(question.getId());
                List<OptionsVo> optionsVos = options.stream().map(option -> OptionsVo.init(option)).collect(Collectors.toList());
                // 构造questionsVo
                QuestionsVo questionsVo = QuestionsVo.init(question, optionsVos);
                questionsVos.add(questionsVo);
            }
            // 获取报告id
            Integer reportId = reportApi.find(questionnaire.getId(), UserHolder.getUserId());
            // 构造questionnaireVo
            QuestionnaireVo questionnaireVo = QuestionnaireVo.init(questionnaire, questionsVos);
            if (reportId != null) {
                questionnaireVo.setReportId(reportId.toString());
            }
            // 判断上份问卷是否回答
            Boolean aBoolean = redisTemplate.opsForHash().hasKey(KEY + id, HASHKEY + UserHolder.getUserId());
            if (aBoolean) {
                questionnaireVo.setIsLock(0);
            }
            id = questionnaire.getId();
            questionnaireVos.add(questionnaireVo);
        }
        return questionnaireVos;
    }

    /**
     * 提交问卷答案，生产报告
     *
     * @param answers
     * @return
     */
    public String submit(List<Answers> answers) {
        // 获取问卷分数
        Integer score = optionsApi.getScore(answers);
        // 获取试题id
        String questionId = answers.get(0).getQuestionId();
        // 获取问卷id
        Integer questionnaireId = questionsApi.getQuestionnaireId(questionId);
        Long userId = UserHolder.getUserId();
        Report report = Report.init(score, userId, questionnaireId);
        // 保存报告
        Integer reportId = reportApi.save(report);
        // 记录已答问卷
        redisTemplate.opsForHash().put(KEY + questionnaireId, HASHKEY + userId, "1");
        return reportId.toString();
    }

    /**
     * 查询问卷报告
     *
     * @param reportId
     * @return
     */
    public ReportVo look(Integer reportId) {
        // 查询问卷报告
        Report report = reportApi.look(reportId);
        ReportVo reportVo = ReportVo.init(report);
        // 查询相似用户id
        List<Integer> userIds = reportApi.findIds(report.getDimensions());
        List<SimilarYouVo> similarYouVos = new ArrayList<>();
        if (userIds != null) {
            // 存在相似用户
            List<Long> list = userIds.stream().map(v -> Long.valueOf(v.toString())).collect(Collectors.toList());
            Map<Long, UserInfo> userInfos = userInfoApi.findByIds(list, null);
            if (userInfos != null) {
                userInfos.remove(UserHolder.getUserId());
                userInfos.forEach((k, v) -> {
                    SimilarYouVo similarYouVo = SimilarYouVo.init(v);
                    similarYouVos.add(similarYouVo);
                });
            }
            reportVo.setSimilarYou(similarYouVos);
        }
        return reportVo;
    }
}
